'''
baseclass.py

Copyright 2009 Xavier Mendez Navarro aka Javi

This file is part of pysqlin

pysqlin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation version 2 of the License.

pysqlin is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with pysqlin; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
'''

from framework.roles import Observer
from framework.roles import Printer
from framework.myexceptions import MyException
from framework.facade import Facade
from framework.sqlinjection import SQLInjection
from framework.mymodel import InjectionData
from framework.interfaces import IFilter

import threading

class BFilter:
    def process_injection_data(self, injection_data):
	url = injection_data[InjectionData.URL]
	post_data = injection_data[InjectionData.POST_DATA]
	cookie = injection_data[InjectionData.COOKIE]

	try:
	    if IFilter.URL in self.type() and url:
		url = self.transform(url)
		if url is None: raise MyException('Filter transform method must return a string')

	    if IFilter.POST_DATA in self.type() and post_data:
		post_data = self.transform(post_data)
		if post_data is None: raise MyException('Filter transform method must return a string')

	    if IFilter.COOKIE in self.type() and cookie:
		cookie = self.transform(cookie)
		if cookie is None: raise MyException('Filter transform method must return a string')
	except Exception, error:
	    raise MyException, 'The request filter %s has caused an error: %s' % (self.name(), error)

	injection_data[InjectionData.URL] = url 
	injection_data[InjectionData.POST_DATA] = post_data 
	injection_data[InjectionData.COOKIE] = cookie 

	return injection_data

    def process_query(self, query):
	try:
	    query = self.transform(query)
	except Exception, error:
	    raise MyException, 'The request filter %s has caused an error: %s' % (self.name(), error)

	if query is None:
	    raise MyException('Filter transform method must return a string')

	return query


class BInjector(Printer, threading.Thread):
    def __init__(self, api):
	self.api = api
        threading.Thread.__init__(self)

    def init(self, sqli, boss_queue, res_queue):
	self.sqli = sqli
	self.boss_queue = boss_queue
	self.res_queue = res_queue
	self.id = None

    def run(self):
	while 1:
	    frow, trow = self.boss_queue.get(True, 365 * 24 * 60 * 60)

	    if frow is None: 
		break

	    try:
		self.launch_job(frow, trow)
	    except Exception, e:
		self.put_exception(e)
		break

    def put_results(self, row, item):
	self.res_queue.put_normal((int(row), item))

    def no_results(self, row):
	self.res_queue.put_high((int(row), None))

    def put_exception(self, e):
	self.res_queue.put_high((None, e))

class BPlugin(object, Observer, Printer):
    def __init__(self, api):
	self.api = api

#    # ------------------------------------------------
#    # Event handling
#    # ------------------------------------------------
#    def subscribe_par_event(self, functor, event_name):
#	self.__controller.ehandler.subscribe(functor, 'PARAMETER ' + 'root.' + event_name)

    # ------------------------------------------------
    # Sql injection
    # ------------------------------------------------
    def make_injection(self, query, from_row = None, to_row = None):
	sqli = SQLInjection(self.get_session_data(), query, Facade().get_filters(), None)
	return sqli.make(from_row, to_row)

    # ------------------------------------------------
    # Session handling
    # ------------------------------------------------
    def get_session_data(self):
	return Facade().get_session().inj_data

    # ------------------------------------------------
    # help functions
    # ------------------------------------------------
    def query_requester(self, steps):
	data = self.get_session_data()

	for desc, stack_query_str in steps:
	    print "- %s: %s" % (desc, stack_query_str)
	    word = self.make_injection(Query(select=data['firstquery']), Query(select=stack_query_str))
	    if word is None:
		print "Error: Data not found!"
		return False

	return True
